/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.compomics.fspike.gui.taxonomytree;

import com.compomics.fspike.gui.taxonomytree.rendering.TaxonomyTreeIconRenderer;
import com.compomics.fspike.gui.taxonomytree.rendering.DefaultTaxonomyTreeNode;
import com.compomics.fspike.gui.taxonomytree.rendering.DefaultTaxonomyTreeModel;
import com.compomics.fspike.contentprovider.uniprotontology.UniprotTaxonomyLookupService;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

/**
 *
 * @author Kenneth
 */
public class JUniprotTaxonomyTree extends NCBITaxonomyTree {

    private JFrame parent = null;
    private TaxonomyTreeIconRenderer taxonomyTreeIconRenderer;

    public JUniprotTaxonomyTree(JFrame parent) throws MalformedURLException {
        super();
        this.parent = parent;
        initTree();
    }

    public JUniprotTaxonomyTree() throws MalformedURLException {
        super();
        initTree();
    }

    @Override
    public List<DefaultTaxonomyTreeNode> getChildren(DefaultTaxonomyTreeNode node) {
        LinkedHashMap<String, String> childrenNameMap = node.getChildrenNameMap();
        List<DefaultTaxonomyTreeNode> childrenList = new LinkedList<>();
        if (childrenNameMap != null && !childrenNameMap.isEmpty()) {
            for (String aChildName : childrenNameMap.keySet()) {
                DefaultTaxonomyTreeNode child = new DefaultTaxonomyTreeNode(aChildName);
                child.setUrl(childrenNameMap.get(aChildName));
                childrenList.add(child);
            }
        }
        return childrenList;
    }

    @Override
    public DefaultTaxonomyTreeModel openChildren(DefaultTaxonomyTreeNode node) throws MalformedURLException, IOException {
        DefaultTaxonomyTreeModel model = (DefaultTaxonomyTreeModel) this.getModel();
        try {
            UniprotTaxonomyLookupService.updateNode(node);
            for (String aChildName : node.getChildrenNameMap().keySet()) {
                if (searchNode(node, aChildName) == null) {
                    DefaultTaxonomyTreeNode childNode = new DefaultTaxonomyTreeNode(aChildName);
                    childNode.setUrl(node.getChildrenNameMap().get(aChildName));
                    model.insertNodeInto(childNode, node, node.getChildCount());
                }
            }
            setModel(model);
        } catch (URISyntaxException ex) {
            Logger.getLogger(JUniprotTaxonomyTree.class.getName()).log(Level.SEVERE, null, ex);
        }

        return model;
    }

    public void buildSearchedPathToRoot(DefaultTaxonomyTreeNode node) throws MalformedURLException, IOException {
        DefaultTaxonomyTreeModel model = (DefaultTaxonomyTreeModel) getModel();
        LinkedList<DefaultTaxonomyTreeNode> lineagePath = new LinkedList<>();
        lineagePath.add(node);
        DefaultTaxonomyTreeNode parentNode = node;

        while (!parentNode.toString().equalsIgnoreCase("cellular organisms")) {
            //build the parent node...
            try {
                UniprotTaxonomyLookupService.updateNode(parentNode);
                DefaultTaxonomyTreeNode tempNode = new DefaultTaxonomyTreeNode(parentNode.getParentName());
                tempNode.setUrl(parentNode.getParentURL());
                //add to the path
                lineagePath.addFirst(parentNode);
                parentNode = tempNode;
            } catch (NullPointerException | URISyntaxException ex) {
                Logger.getLogger(JUniprotTaxonomyTree.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        //we have the full path here...
        DefaultTaxonomyTreeNode tempParent = (DefaultTaxonomyTreeNode) model.getRoot();
        for (DefaultTaxonomyTreeNode aNode : lineagePath) {
            //break on the parent node
            if (aNode.toString().equalsIgnoreCase(node.toString())) {
                break;
            }
            DefaultTaxonomyTreeNode aNodeToInsert = searchNode((DefaultTaxonomyTreeNode) tempParent, aNode.toString());
            //check if the node exists?
            if (aNodeToInsert == null) {
                aNodeToInsert = aNode;
                //insert this node in the previous one
                model.insertNodeInto(aNodeToInsert, tempParent, tempParent.getChildCount());
                //make the current child the next parent
            }

            tempParent = aNodeToInsert;
        }
        collapseToNodeOnly(tempParent);
    }

    /**
     * initializes the species tree
     *
     */
    private void initTree() throws MalformedURLException {
        selectionModel.setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
        //remove default nodes
        setRootVisible(false);
        setShowsRootHandles(true);
        DefaultTaxonomyTreeNode root = new DefaultTaxonomyTreeNode("cellular organisms");
        root.setUrl("http://www.uniprot.org/taxonomy/131567");
        DefaultTaxonomyTreeModel lineageTreeModel = new DefaultTaxonomyTreeModel(root);
        setCellRenderer(taxonomyTreeIconRenderer);
        root.setHasChildren(true);
        lineageTreeModel.setRoot(root);
        HashMap<String, String> primordials = new HashMap<>();
        //  "Archaea",
        primordials.put("Archaea", "http://www.uniprot.org/taxonomy/2157");
        primordials.put("Bacteria", "http://www.uniprot.org/taxonomy/2");
        primordials.put("Eukaryota", "http://www.uniprot.org/taxonomy/2759");
        // "Viroids",
        //"Viruses",
        //"Other",
        //"Unclassified"};
        for (String aPrimordial : primordials.keySet()) {
            DefaultTaxonomyTreeNode primordialNode = new DefaultTaxonomyTreeNode(aPrimordial);
            primordialNode.setUrl(primordials.get(aPrimordial));
            primordialNode.setParentURL("www.uniprot.org/taxonomy/131567");
            primordialNode.setIconName(aPrimordial.substring(0, 2).toUpperCase());
            lineageTreeModel.insertNodeInto(primordialNode, root, root.getChildCount());
        }
        setModel(lineageTreeModel);
        // forceLookAndFeel();
        repaint();
        revalidate();
    }

    private void forceLookAndFeel() {
        try {
            NimbusLookAndFeel laf = new NimbusLookAndFeel();
            UIManager.setLookAndFeel(laf);
            UIDefaults newUIDefaults = laf.getDefaults();
            newUIDefaults.put("Tree.drawHorizontalLines", true);
            newUIDefaults.put("Tree.drawVerticalLines", true);
            newUIDefaults.put("Tree.showRootHandles", false);
            newUIDefaults.put("Tree.dropLineColor", "#d6d9df (214,217,223)");
            newUIDefaults.put("Tree.line", "#d6d9df (214,217,223)");
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            Logger.getLogger(JUniprotTaxonomyTree.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void scrollPathToVisible(TreePath path) {
        super.scrollPathToVisible(path);
        if (path != null) {
            setSelectionPath(path);
        }
    }

}
